package heap

func (self *Class) isAssignableFrom(other *Class) bool {
	s, t := other, self
	if s == t {
		return true
	}
	if !s.IsArray() {
		if !s.IsInterface() {
			if !t.IsInterface() {
				return s.IsSubClassOf(t)
			} else {
				return s.IsImplements(t)
			}
		} else {
			if !t.IsInterface() {
				return t.isJ1Object()
			} else {
				return t.IsSuperInterfaceOf(s)
			}
		}
	} else {
		if !t.IsArray() {
			if !t.IsInterface() {
				return t.isJ1Object()
			} else {
				return t.isJ1Cloneable() || t.isJ1Serializable()
			}
		} else {
			sc := s.ComponentClass()
			tc := t.ComponentClass()
			return sc == tc || tc.isAssignableFrom(sc)
		}
	}
}

func (self *Class) IsSubClassOf(clazz *Class) bool {
	for c := self.superClass; c != nil; c = c.superClass {
		if c == clazz {
			return true
		}
	}
	return false
}

func (self *Class) IsImplements(iface *Class) bool {
	for c := self; c != nil; c = c.superClass {
		for _, i := range c.interfaces {
			if i == iface || i.IsSubInterfaceOf(iface) {
				return true
			}
		}
	}
	return false
}

func (self *Class) IsSubInterfaceOf(iface *Class) bool {
	for _, superInterface := range self.interfaces {
		if superInterface == iface || superInterface.IsSubInterfaceOf(iface) {
			return true
		}
	}
	return false
}

func (self *Class) IsSuperClassOf(other *Class) bool {
	return other.IsSubClassOf(self)
}

func (self *Class) IsSuperInterfaceOf(iface *Class) bool {
	return iface.IsSubInterfaceOf(self)
}

func (self *Class) isJ1Object() bool {
	return self.name == "java/lang/Object"
}

func (self *Class) isJ1Cloneable() bool {
	return self.name == "java/lang/Cloneable"
}

func (self *Class) isJ1Serializable() bool {
	return self.name == "java/io/Serializable"
}
